home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-01
/
cmouse.zip
/
CMOUSE.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1991-04-02
|
15KB
|
600 lines
/*
cmouse.cpp
4-2-90
Microsoft mouse interrupt functions
Copyright 1991
John W. Small
All rights reserved
PSW / Power SoftWare
P.O. Box 10072
McLean, Virginia 22102 8072
(703) 759-3838
Works consulted:
"Microsoft Mouse Programmer's Reference."
Bellevue, Washington: Microsoft Press, 1989.
"Microsoft Mouse Programmer's Reference Guide."
Bellevue, Washington: Microsoft Press, 1986.
Refer to above works for mouse function
documentation.
*/
#include <dos.h> /* union REGS, struct SREGS, */
/* int86(), int86x(), */
/* geninterrupt(), enable() */
#include <cmouse.hpp>
MicrosoftMouse MM; // Only instance allowed!
unsigned MicrosoftMouse::Xcell[] = {
16,16,8,8,2,2,1,8,1,1,1,1,1,2,1,1,1,1,1,2};
unsigned MicrosoftMouse::Ycell[] = {
8,8,8,8,1,1,1,8,1,1,1,1,1,1,1,1,1,1,1,1};
unsigned MicrosoftMouse::LeftTopOfs[] = {
1,1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0};
MicrosoftMouse::~MicrosoftMouse()
{
on();
restore();
clearAltInterrupts();
reset();
state = origState;
restore();
}
/* Stack overflow check overwrites AX : do not compile with -N */
/* Do not call! Use to cookbook your own if needed. */
#pragma argsused
void interrupt MMautoEventHandler(
unsigned iBP,
unsigned vertMickeys, /* di */
unsigned horzMickeys, /* si */
unsigned iDS,
unsigned iES,
unsigned y, /* dx */
unsigned x, /* cx */
unsigned buttonState, /* bx */
unsigned conditionMask, /* ax */
unsigned iIP,
unsigned iCS,
unsigned pseudoFlags) /* not present */
{
MM.eventTime = (*(long far *)MK_FP(0x0040,0x006C));
enable();
MM.eventCount++;
MM.eventFlags = conditionMask;
MM.leftPressed = (buttonState & MBleft)? 1 : 0;
MM.rightPressed = (buttonState & MBright)? 1 : 0;
MM.x = MM.physicalX(x);
MM.y = MM.physicalY(y);
MM.horzMickeys = horzMickeys;
MM.vertMickeys = vertMickeys;
if (conditionMask & MEmoved)
MM.eventMoved++;
if (conditionMask & MEleftPressed) {
MM.leftPressed = 1;
MM.lastLeftPressX = MM.x;
MM.lastLeftPressY = MM.y;
MM.leftPresses++;
MM.buttonRequested = MBleft;
if ((MM.leftClickTime > MM.eventTime) ||
((MM.eventTime - MM.leftClickTime)
> MM.clickTimeOut)) {
MM.leftClickTime = MM.eventTime;
MM.leftClicks = 0;
}
}
if (conditionMask & MEleftReleased) {
MM.leftPressed = 0;
MM.lastLeftReleaseX = MM.x;
MM.lastLeftReleaseY = MM.y;
MM.leftReleases++;
MM.buttonRequested = MBleft;
if ((MM.leftClickTime > MM.eventTime) ||
((MM.eventTime - MM.leftClickTime)
> MM.clickTimeOut)) {
MM.leftClickTime = MM.eventTime;
MM.leftClicks = 0;
}
else
MM.leftClicks++;
}
if (conditionMask & MErightPressed) {
MM.rightPressed = 1;
MM.lastRightPressX = MM.x;
MM.lastRightPressY = MM.y;
MM.rightPresses++;
MM.buttonRequested = MBright;
if ((MM.rightClickTime > MM.eventTime) ||
((MM.eventTime - MM.rightClickTime)
> MM.clickTimeOut)) {
MM.rightClickTime = MM.eventTime;
MM.rightClicks = 0;
}
}
if (conditionMask & MErightReleased) {
MM.rightPressed = 0;
MM.lastRightReleaseX = MM.x;
MM.lastRightReleaseY = MM.y;
MM.rightReleases++;
MM.buttonRequested = MBright;
if ((MM.rightClickTime > MM.eventTime) ||
((MM.eventTime - MM.rightClickTime)
> MM.clickTimeOut)) {
MM.rightClickTime = MM.eventTime;
MM.rightClicks = 0;
}
else
MM.rightClicks++;
}
/*
Convert from Interrupt stack frame to FAR call stack
frame then return from FAR. Since the mouse driver
FAR calls this interrupt handler instead of issuing
an interrupt call to get here, this event handler
needs to return from a FAR call instead of returning
from an interrupt! A Turbo C++ interrupt function
was used since it automatically restores DS to the
data segment. The mouse driver also passes
parameters in registers instead of on the
stack. TC++'s interrupt keyword forces the function
to automatically stack these registers so that they
can be accessed.
*/
asm mov ax,iDS /* restore DS */
asm mov ds,ax
conditionMask = iBP; /* skip over parameters */
asm add bp,OFFSET conditionMask
asm mov sp,bp /* exit far proc */
asm pop bp
asm retf
}
MicrosoftMouse::MicrosoftMouse()
{
unsigned char far *vec;
vmode = 0;
present = 0;
buttons = 0;
leftPressed = 0; rightPressed = 0;
x = 0; y = 0;
lastLeftPressX = 0; lastLeftPressY = 0;
leftPresses = 0;
buttonRequested = MBleft;
lastLeftReleaseX = 0; lastLeftReleaseY = 0;
leftReleases = 0;
lastRightPressX = 0; lastRightPressY = 0;
rightPresses = 0;
lastRightReleaseX = 0; lastRightReleaseY = 0;
rightReleases = 0;
vertMickeys= 0; horzMickeys = 0;
handler = (MouseHandler) 0;
callMask = 0;
eventMask = 0x001F;
eventFlags = 0;
eventCount = 0;
eventMoved = 0;
eventTime = 0;
clickTimeOut = 10;
leftClickTime = 0;
leftClicks = 0;
rightClickTime = 0;
rightClicks = 0;
origState = (void *) 0;
state = (void *) 0;
stateSize = 0;
altHandler = (MouseHandler) 0;
altCallMask = 0;
horzPercent = 50; vertPercent = 50;
doublePercent = 50;
crtPage = 0;
mouseIntrVector = (MouseDriver) 0;
language = MLenglish;
driverVersion = 0;
IRQ = -1;
typeRequired = MTunknown;
vec = (unsigned char far *) getvect(MOUSE_INT);
if (!vec || (*vec == 0xCF)) /* IRET */
return;
reset();
driver();
if (!present)
return;
save();
origState = state;
state = (void *) 0;
}
void MicrosoftMouse::reset() /* MF0 */
{
_AH = 0x0F;
geninterrupt(0x10);
vmode = _AL;
_AX = 0;
geninterrupt(MOUSE_INT);
if (_AX) {
buttons = _BX;
present = 1;
}
else
buttons = present = 0;
}
void MicrosoftMouse::updateStatusInfo() /* MF3 */
{
unsigned buttons;
_AX = 3;
geninterrupt(MOUSE_INT);
buttons = _BX;
x = _CX;
y = _DX;
leftPressed = (buttons & MBleft)? 1 : 0;
rightPressed = (buttons & MBright)? 1 : 0;
x = physicalX(x);
y = physicalY(y);
}
void MicrosoftMouse::gotoxy() /* MF4 */
{
unsigned vx, vy;
vx = virtualX(x);
vy = virtualY(y);
_CX = vx;
_DX = vy;
_AX = 4;
geninterrupt(MOUSE_INT);
}
void MicrosoftMouse::updatePressInfo() /* MF5 */
{
union REGS rgs;
rgs.x.ax = 5;
rgs.x.bx = buttonRequested >> 1;
(void) int86(MOUSE_INT,&rgs,&rgs);
leftPressed = (rgs.x.ax & MBleft)? 1 : 0;
rightPressed = (rgs.x.ax & MBright)? 1 : 0;
if (buttonRequested == MBleft) {
leftPresses = rgs.x.bx;
lastLeftPressX = physicalX(rgs.x.cx);
lastLeftPressY = physicalY(rgs.x.dx);
}
else {
rightPresses = rgs.x.bx;
lastRightPressX = physicalX(rgs.x.cx);
lastRightPressY = physicalY(rgs.x.dx);
}
}
void MicrosoftMouse::updateReleaseInfo() /* MF6 */
{
union REGS rgs;
rgs.x.ax = 6;
rgs.x.bx = buttonRequested >> 1;
(void) int86(MOUSE_INT,&rgs,&rgs);
leftPressed = (rgs.x.ax & MBleft)? 1 : 0;
rightPressed = (rgs.x.ax & MBright)? 1 : 0;
if (buttonRequested == MBleft) {
leftReleases = rgs.x.bx;
lastLeftReleaseX = physicalX(rgs.x.cx);
lastLeftReleaseY = physicalY(rgs.x.dx);
}
else {
rightReleases = rgs.x.bx;
lastRightReleaseX = physicalX(rgs.x.cx);
lastRightReleaseY = physicalY(rgs.x.dx);
}
}
void MicrosoftMouse::trap(unsigned x1, unsigned y1,
unsigned x2, unsigned y2)
{ /* MF7, MF8 */
unsigned d1, d2;
d1 = virtualX(x1);
d2 = virtualX(x2);
_CX = d1;
_DX = d2;
_AX = 7;
geninterrupt(MOUSE_INT);
d1 = virtualY(y1);
d2 = virtualY(y2);
_CX = d1;
_DX = d2;
_AX = 8;
geninterrupt(MOUSE_INT);
}
void MicrosoftMouse::graphicsCursor(signed char horzHS,
signed char vertHS,
unsigned far *scrCurMask) /* MF9 */
{
unsigned h, v;
h = ((unsigned) horzHS) * Xcell[vmode];
v = ((unsigned) vertHS) * Ycell[vmode];
_ES = FP_SEG(scrCurMask);
_DX = FP_OFF(scrCurMask);
_BX = h;
_CX = v;
_AX = 9;
geninterrupt(MOUSE_INT);
}
void MicrosoftMouse::swapInterrupts() /* MF20 */
{
union REGS rgs;
struct SREGS srgs;
rgs.x.ax = 20;
rgs.x.cx = callMask;
rgs.x.dx = FP_OFF(handler);
srgs.es = FP_SEG(handler);
(void) int86x(MOUSE_INT,&rgs,&rgs,&srgs);
callMask = rgs.x.cx;
handler = (MouseHandler) MK_FP(srgs.es,rgs.x.dx);
}
void MicrosoftMouse::autoEventUpdate() /* N/A */
{
handler = (MouseHandler) MMautoEventHandler;
callMask = eventMask;
swapInterrupts();
}
void MicrosoftMouse::save() /* MF21, MF22 */
{
union REGS rgs;
struct SREGS srgs;
if (state) return;
_AX = 21;
geninterrupt(MOUSE_INT);
stateSize = _BX;
if ((state = (void *) new char [stateSize])
== (void *) 0) return;
srgs.es = FP_SEG((void far *)state);
rgs.x.dx = FP_OFF((void far *)state);
rgs.x.ax = 22;
(void) int86x(MOUSE_INT,&rgs,&rgs,&srgs);
}
void MicrosoftMouse::restore() /* MF23 */
{
union REGS rgs;
struct SREGS srgs;
if(!state) return;
srgs.es = FP_SEG((void far *)state);
rgs.x.dx = FP_OFF((void far *)state);
rgs.x.ax = 23;
(void) int86x(MOUSE_INT,&rgs,&rgs,&srgs);
delete state;
state = (void *) 0;
}
void MicrosoftMouse::clearAltInterrupts() /* N/A */
{
altHandler = (MouseHandler) 0;
altCallMask = MEshiftPressed
| MEctrlPressed | MEaltPressed;
setAltInterrupt();
altCallMask = MEshiftPressed | MEctrlPressed;
setAltInterrupt();
altCallMask = MEshiftPressed | MEaltPressed;
setAltInterrupt();
altCallMask = MEctrlPressed | MEaltPressed;
setAltInterrupt();
altCallMask = MEshiftPressed;
setAltInterrupt();
altCallMask = MEctrlPressed;
setAltInterrupt();
altCallMask = MEaltPressed;
setAltInterrupt();
}
void MicrosoftMouse::off() /* MF31 */
{
union REGS rgs;
struct SREGS srgs;
if (mouseIntrVector) return;
rgs.x.ax = 31;
(void) int86x(MOUSE_INT,&rgs,&rgs,&srgs);
if (rgs.x.ax == 0xFFFF) return;
mouseIntrVector = getvect(MOUSE_INT);
setvect(MOUSE_INT, (MouseDriver)
MK_FP(srgs.es,rgs.x.bx));
}
void MicrosoftMouse::on() /* MF32 */
{
if (!mouseIntrVector) return;
setvect(MOUSE_INT, mouseIntrVector);
mouseIntrVector = (MouseDriver) 0;
_AX = 32;
geninterrupt(MOUSE_INT);
}
void MicrosoftMouse::softReset() /* MF33 */
{
_AX = 0x0F00;
geninterrupt(0x10);
vmode = _AL;
_AX = 33;
geninterrupt(MOUSE_INT);
present = ((_AX == 0xFFFF) && (_BX == 2))? 1 : 0;
}
void MicrosoftMouse::driver() /* MF36 */
{
union REGS rgs;
rgs.x.ax = 36;
(void) int86(MOUSE_INT,&rgs,&rgs);
driverVersion = rgs.x.bx;
IRQ = rgs.h.cl;
typeRequired = rgs.h.ch;
}
// To use cmouse in your application
// comment out //#define TEST_CMOUSE_CPP
#define TEST_CMOUSE_CPP
#ifdef TEST_CMOUSE_CPP
#include <conio.h> /* clrscr(), gotoxy(), cprintf() */
#include <stdlib.h>
#include <graphics.h>
char *mice[] = {
"Unknown", "Bus", "Serial",
"InPort", "PS2", "HP"
};
void MouseReport()
{
(void) cprintf("\r\nMouse Driver Version : %d.%d%d",
MM.driverVersion >> 8,
(MM.driverVersion & 0x00F0) >> 4,
(MM.driverVersion & 0x000F));
(void) cprintf("\r\nRequires : %s Mouse",mice[MM.typeRequired]);
if (MM.present)
(void) cprintf("\r\nMouse has %2d buttons.",MM.buttons);
else
(void) cprintf("\r\nMouse not connected!");
(void) cprintf("\r\n\nMouse cursor @ (%3d,%3d)",MM.x,MM.y);
(void) cprintf(" Left : %s",MM.leftPressed? "Down":"Up ");
(void) cprintf(" Right : %s",MM.rightPressed? "Down":"Up ");
(void) cprintf("\r\n%s button requested",
(MM.buttonRequested == MBleft)?
"Left " : "Right");
(void) cprintf("\r\nLeft: Presses : %3d @ (%3d,%3d) ",
MM.leftPresses, MM.lastLeftPressX,
MM.lastLeftPressY);
(void) cprintf("Releases : %3d @ (%3d,%3d)",
MM.leftReleases, MM.lastLeftReleaseX,
MM.lastLeftReleaseY);
(void) cprintf("\r\nRight: Presses : %3d @ (%3d,%3d) ",
MM.rightPresses, MM.lastRightPressX,
MM.lastRightPressY);
(void) cprintf("Releases : %3d @ (%3d,%3d)",
MM.rightReleases, MM.lastRightReleaseX,
MM.lastRightReleaseY);
(void) cprintf("\r\nMickeys : Horz : %10u Vert : %10u",
MM.horzMickeys, MM.vertMickeys);
(void) cprintf("\r\nEvent : Count : %10u Time : %10lu Flags : %10u",
MM.eventCount, MM.eventTime, MM.eventFlags);
(void) cprintf("\r\nClicks : Left : %10u Right : %10u",
MM.leftClicks, MM.rightClicks);
(void) cprintf("\r\n@ time : Left : %10lu Right : %10lu",
MM.leftClickTime, MM.rightClickTime);
}
main()
{
unsigned ec;
int gdriver, gmode, gerror;
int dx, c;
clrscr();
gotoxy(10,20);
cprintf("Press any key to continue ...");
MM.show();
MM.autoEventUpdate();
ec = MM.eventCount;
MM.condOffZone(1,2,71,13);
while (!kbhit()) {
gotoxy(1,1);
MM.condOff();
MouseReport();
MM.show();
while ((ec == MM.eventCount) && !kbhit());
ec = MM.eventCount;
}
getch(); // clear keyboard buffer
gdriver = DETECT;
initgraph(&gdriver, &gmode, "\\borlandc\\bgi");
gerror = graphresult();
if (gerror != grOk) /* an error occurred */
{
clrscr();
cprintf("Not able to demo in graphics mode: %s",
grapherrormsg(gerror));
cprintf("\r\nPress any key to halt:");
getch();
exit(1);
}
MM.reset(); // call after any video mode change.
directvideo = 0; // enable conio i/o in graphics mode
dx = getmaxx() / (getmaxcolor()+1);
clearviewport();
for (c = 0; c <= getmaxcolor(); c++) {
setfillstyle(XHATCH_FILL,c);
bar3d(c*dx,0,(c+1)*dx,getmaxy(),0,0);
}
gotoxy(10,20);
cprintf("Press any key to quit ...");
MM.show();
MM.autoEventUpdate();
ec = MM.eventCount;
MM.condOffZone(0,0,570,208);
while (!kbhit()) {
gotoxy(1,1); // conio remember!
MouseReport();
// CondOff() really belongs before MouseReport
// because conio is so slow I put it here.
// If you XOR_PUT to screen make sure mouse is
// hidden by condOff() or hide() before updating!
MM.condOff();
MM.show();
while ((ec == MM.eventCount) && !kbhit());
ec = MM.eventCount;
}
closegraph();
cputs("If you find cmouse useful and are using it in your");
cputs("\r\napplications, how about telling a friend about it.");
cputs("\r\nCmouse is freeware - I only ask that you leave my");
cputs("\r\ncopyright notice untouched! I will try to answer");
cputs("\r\nas many of your questions and/or comments (time ");
cputs("\r\nand money permitting). Thanks! John CIS: 73757,2233");
cputs("\r\n");
cputs("\r\nPSW / Power SoftWare");
cputs("\r\nP.O. Box 10072");
cputs("\r\nMcLean, Virginia 22102 8072");
cputs("\r\n(703) 759-3838");
cputs("\r\n");
cputs("\r\nThat's all folks!");
cputs("\r\n");
cputs("\r\nPress enter to quit.");
getch();
return 0;
}
#endif